import { defineStore } from "pinia";
import { ref, computed } from "vue";
import type { CallInfo, IncomingCallInfo, CallStatus } from "../types";
import { CallDirection, CallStatus as CallStatusEnum } from "../types";
import * as tauriApi from "../services/tauri-api";

export const useCallStore = defineStore("call", () => {
  // State
  const activeCalls = ref<Map<string, CallInfo>>(new Map());
  const incomingCall = ref<IncomingCallInfo | null>(null);
  const currentCallId = ref<string | null>(null);
  const loading = ref(false);
  const error = ref<string | null>(null);

  // Getters
  const currentCall = computed(() => {
    if (!currentCallId.value) return null;
    return activeCalls.value.get(currentCallId.value) || null;
  });

  const hasActiveCalls = computed(() => activeCalls.value.size > 0);
  const hasIncomingCall = computed(() => incomingCall.value !== null);
  const isInCall = computed(() => {
    return currentCall.value?.status === CallStatusEnum.Connected;
  });

  // Actions
  const makeCall = async (number: string) => {
    loading.value = true;
    error.value = null;
    
    try {
      const callId = await tauriApi.makeCall(number);
      
      const callInfo: CallInfo = {
        id: callId,
        remote_number: number,
        direction: CallDirection.Outbound,
        status: CallStatusEnum.Ringing,
        start_time: new Date().toISOString(),
      };
      
      activeCalls.value.set(callId, callInfo);
      currentCallId.value = callId;
      
      return callId;
    } catch (err) {
      error.value = err instanceof Error ? err.message : "Failed to make call";
      throw err;
    } finally {
      loading.value = false;
    }
  };

  const answerCall = async (callId: string) => {
    loading.value = true;
    error.value = null;
    
    try {
      await tauriApi.answerCall(callId);
      
      const call = activeCalls.value.get(callId);
      if (call) {
        call.status = CallStatusEnum.Connected;
        call.start_time = new Date().toISOString();
        activeCalls.value.set(callId, call);
      }
      
      currentCallId.value = callId;
      incomingCall.value = null;
    } catch (err) {
      error.value = err instanceof Error ? err.message : "Failed to answer call";
      throw err;
    } finally {
      loading.value = false;
    }
  };

  const rejectCall = async (callId: string) => {
    loading.value = true;
    error.value = null;
    
    try {
      await tauriApi.rejectCall(callId);
      
      const call = activeCalls.value.get(callId);
      if (call) {
        call.status = CallStatusEnum.Ended;
        activeCalls.value.set(callId, call);
      }
      
      incomingCall.value = null;
      
      // Remove call after a short delay
      setTimeout(() => {
        activeCalls.value.delete(callId);
      }, 2000);
    } catch (err) {
      error.value = err instanceof Error ? err.message : "Failed to reject call";
      throw err;
    } finally {
      loading.value = false;
    }
  };

  const hangupCall = async (callId: string) => {
    loading.value = true;
    error.value = null;
    
    try {
      await tauriApi.hangupCall(callId);
      
      const call = activeCalls.value.get(callId);
      if (call) {
        call.status = CallStatusEnum.Ended;
        if (call.start_time) {
          const startTime = new Date(call.start_time);
          const duration = Math.floor((Date.now() - startTime.getTime()) / 1000);
          call.duration = duration;
        }
        activeCalls.value.set(callId, call);
      }
      
      if (currentCallId.value === callId) {
        currentCallId.value = null;
      }
      
      // Remove call after a short delay
      setTimeout(() => {
        activeCalls.value.delete(callId);
      }, 2000);
    } catch (err) {
      error.value = err instanceof Error ? err.message : "Failed to hangup call";
      throw err;
    } finally {
      loading.value = false;
    }
  };

  const muteCall = async (callId: string, muted: boolean) => {
    try {
      await tauriApi.muteCall(callId, muted);
    } catch (err) {
      error.value = err instanceof Error ? err.message : "Failed to mute call";
      throw err;
    }
  };

  const setIncomingCall = (incomingCallInfo: IncomingCallInfo) => {
    incomingCall.value = incomingCallInfo;
    
    // Add to active calls
    const callInfo: CallInfo = {
      id: incomingCallInfo.call_id,
      remote_number: incomingCallInfo.caller_number,
      remote_name: incomingCallInfo.caller_name,
      direction: CallDirection.Inbound,
      status: CallStatusEnum.Ringing,
    };
    
    activeCalls.value.set(incomingCallInfo.call_id, callInfo);
  };

  const updateCallStatus = (callId: string, status: CallStatus, duration?: number) => {
    const call = activeCalls.value.get(callId);
    if (call) {
      call.status = status;
      if (duration !== undefined) {
        call.duration = duration;
      }
      activeCalls.value.set(callId, call);
    }
  };

  const clearError = () => {
    error.value = null;
  };

  const clearIncomingCall = () => {
    incomingCall.value = null;
  };

  return {
    // State
    activeCalls,
    incomingCall,
    currentCallId,
    loading,
    error,
    
    // Getters
    currentCall,
    hasActiveCalls,
    hasIncomingCall,
    isInCall,
    
    // Actions
    makeCall,
    answerCall,
    rejectCall,
    hangupCall,
    muteCall,
    setIncomingCall,
    updateCallStatus,
    clearError,
    clearIncomingCall,
  };
});